package com.zone.lib.download.execute;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.zone.lib.download.bean.RequestInfo;
import com.zone.lib.download.enums.AppStatusEnum;
import com.zone.lib.download.bean.DownloadInfo;
import com.zone.lib.download.db.entity.Download;
import com.zone.lib.download.install.AndroidP;
import com.zone.lib.download.utils.AppStatusUpdateNotify;
import com.zone.lib.download.utils.DateUtils;
import com.zone.lib.download.utils.LogUtils;
import com.zone.sdk.common.http.callback.ResultCallBack;
import com.zone.sdk_api.ApiManager;
import com.zone.vehicle.sdk.module.superapp.request.AppsDownloadRequest;
import com.zone.vehicle.sdk.module.superapp.vehicle.utils.NetUtil;

import org.apache.commons.lang3.ObjectUtils;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;

import okhttp3.ResponseBody;

public class DownloadTask implements Runnable {

    public static final String TAG = DownloadTask.class.getSimpleName();

    private Context context;
    private RequestInfo requestInfo;
    private DownloadInfo downloadInfo;
    private Download mDownload;
    private boolean wait;
    private boolean isPause;
    private boolean cancel = false;

    public DownloadTask(Context context, RequestInfo requestInfo) {
        this.context = context;
        this.requestInfo = requestInfo;
        this.downloadInfo = requestInfo.getDownloadInfo();

        mDownload = downloadInfo.getDownload();
        long location = 0;
        long fileSize = 0;
        if (mDownload != null) {
            location = mDownload.getDownloadLocation();
            fileSize = mDownload.getSize();

            if (location == 0) {
                if (downloadInfo.getFile().exists()) {
                    downloadInfo.getFile().delete();
                }
            } else {
                //因为未知的原因, 这个文件不存在了,(虽然数据库记录表明我们的确已经下载过了),所以我们要从头开始
                if (!downloadInfo.getFile().exists()) {
                    LogUtils.i(TAG, "file = " + downloadInfo.getFile());
                    Log.i(TAG, "数据库记录表明我们下载过该文件, 但是现在该文件不存在,所以从头开始");
                    location = 0;
                    fileSize = 0;
                }
            }
        } else {
            if (downloadInfo.getFile().exists()) {
                downloadInfo.getFile().delete();
            }
        }
        mDownload.setSize(fileSize);
        mDownload.setDownloadLocation(location);
    }

    public RequestInfo getRequestInfo() {
        return requestInfo;
    }

    @Override
    public void run() {
        downloadOkhttp();
    }

    public void waiting() {
        wait = true;
        if (ObjectUtils.isNotEmpty(mDownload)){
            mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_WAIT.CODE);
            AppStatusUpdateNotify.appNotify(context, mDownload);
        }
    }

    public void pause() {
        isPause = true;
        if (ObjectUtils.isNotEmpty(mDownload)){
            mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_PAUSE.CODE);
            AppStatusUpdateNotify.appNotify(context, mDownload);
        }
    }

    public void cancel() {
        cancel = true;
    }

    public void restart() {
        isPause = false;
    }

    public int getStatus() {
        if (null != mDownload) {
            return mDownload.getDownloadStatus();
        }
        return AppStatusEnum.DOWNLOAD_FAIL.CODE;
    }

    public void setFileStatus(int status) {
        mDownload.setDownloadStatus(status);
    }

    public void sendBroadcast(Intent intent) {
        context.sendBroadcast(intent);
    }

    public DownloadInfo getDownLoadInfo() {
        return downloadInfo;
    }

    public Download getDownload() {
        return mDownload;
    }

    private void downloadOkhttp(){
        if (ObjectUtils.isNotEmpty(mDownload)){
            LogUtils.i(TAG, "准备开始下载");
            mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_PREPARE.CODE);
            mDownload.setCreateTime(DateUtils.getStringDate());
            AppStatusUpdateNotify.appNotify(context, mDownload);

            AppsDownloadRequest request = getAppsDownloadRequest();
            try {
                RandomAccessFile accessFile = new RandomAccessFile(downloadInfo.getFile(), "rwd");
                accessFile.seek(mDownload.getDownloadLocation());
            } catch (IOException e) {
                e.printStackTrace();
            }

            ApiManager.getInstance().appsDownload(request, new ResultCallBack<ResponseBody>() {
                @Override
                public void onSuccess(ResponseBody responseBody) {
                    LogUtils.i(TAG, "appsDownload onSuccess");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            download(responseBody);
                        }
                    }).start();
                }

                @Override
                public void onError(String errorCode, String message) {
                    LogUtils.e(TAG, "onError errorCode"+errorCode+" message="+message);
                    mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_FAIL.CODE);
                    AppStatusUpdateNotify.appNotify(context, mDownload);
                }

                @Override
                public void onComplete() {

                }
            });
        }
    }

    @NotNull
    private AppsDownloadRequest getAppsDownloadRequest() {
        AppsDownloadRequest request = new AppsDownloadRequest();
        request.setType(mDownload.getAppType());
        request.setAppCode(mDownload.getCode());
        if (mDownload.getDownloadLocation() == 0){
            request.setMode("0");
            request.setPoint("0");
            request.setStartPoint("0");
        }else {
            request.setMode("1");
            request.setPoint(String.valueOf(mDownload.getDownloadLocation()));
            request.setStartPoint(String.valueOf(mDownload.getDownloadLocation()));
        }
        request.setUserId(downloadInfo.getUserId());
        request.setVin(downloadInfo.getVin());
        LogUtils.i(TAG, "download request="+ JSON.toJSONString(request));
        return request;
    }

    @SuppressLint("NewApi")
    private void download(ResponseBody responseBody){

        InputStream is = null;
        FileOutputStream fos = null;
        mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_LOADING.CODE);
        AppStatusUpdateNotify.appNotify(context, mDownload);

        try {
            File dir = new File(context.getCacheDir(), "download");
            if (!dir.exists()){
                dir.mkdirs();
            }
            File saveFile = new File(dir, mDownload.getCode()+".apk");
            long total = responseBody.contentLength();
            mDownload.setTotal(total);
            mDownload.setSize(total);
            LogUtils.i(TAG, "total------>" + total);
            is = responseBody.byteStream();
            fos = new FileOutputStream(saveFile);
            byte[] buffer = new byte[1024 * 8];
            int offset;
            RandomAccessFile accessFile = new RandomAccessFile(downloadInfo.getFile(), "rwd");
            accessFile.seek(mDownload.getDownloadLocation());
            long millis = SystemClock.uptimeMillis();
            while ((offset = is.read(buffer)) != -1) {
                if (cancel){
                    LogUtils.i(TAG, "下载过程 取消 ");
                    return;
                }
                if (isPause) {
                    LogUtils.i(TAG, "下载过程 设置了");
                    mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_PAUSE.CODE);
                    downloadInfo.setAction(AppStatusEnum.DOWNLOAD_PAUSE.CODE);
                    AppStatusUpdateNotify.appNotify(context, mDownload);
                    return;
                }

                accessFile.write(buffer, 0, offset);
                long location = mDownload.getDownloadLocation() + offset;
                mDownload.setDownloadLocation(location);
//                LogUtils.i(TAG, "downloading app="+mDownload.getCode()+" location="+location);
                mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_LOADING.CODE);
                if (SystemClock.uptimeMillis() - millis >= 1000 || mDownload.getDownloadLocation() == mDownload.getTotal()) {
                    millis = SystemClock.uptimeMillis();
                    if (mDownload.getDownloadLocation() == mDownload.getTotal()){
                        mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_COMPLETE.CODE);
                    }
                    AppStatusUpdateNotify.appNotify(context, mDownload);
                    if (!NetUtil.inspectNet(context)) {
                        LogUtils.i(TAG, "下载过程 网络断开");
                        mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_PAUSE.CODE);
                        downloadInfo.setAction(AppStatusEnum.DOWNLOAD_PAUSE.CODE);
                        AppStatusUpdateNotify.appNotify(context, mDownload);
                        return;
                    }
                }
            }
            AndroidP.install28(context, mDownload);
        } catch (IOException e) {
            Log.e("download", e.toString());
            mDownload.setDownloadStatus(AppStatusEnum.DOWNLOAD_FAIL.CODE);
            AppStatusUpdateNotify.appNotify(context, mDownload);
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                Log.e("download", e.toString());
            }
        }
    }

}
